package com.ims.client.util;


import com.alibaba.fastjson.JSONObject;
import com.ims.client.constant.*;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.NetworkIF;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

public class GenerateStatusInfoUtil {

    public static final OperatingSystem operatingSystem = new SystemInfo().getOperatingSystem();
    public static final HardwareAbstractionLayer hardware = new SystemInfo().getHardware();


    public static JSONObject getAllStatesInfo() {
        JSONObject result = new JSONObject();

        String deviceId = "";
        if ("LINUX".equals(System.getProperty("os.name").toUpperCase())){
            deviceId = GetDeviceIdUtil.getLinuxDeviceId();
        }else{
            deviceId = GetDeviceIdUtil.getWindowsDeviceId();
        }

        result.put(HardwareInfoField.DEVICE_ID, deviceId);
        result.put(HardwareInfoField.DEVICE_NAME, DeviceNameUtil.getDeviceName());
        result.put(HardwareInfoField.CPU_STATUS, getCpuStatusInfo());
//        result.put(HardwareInfoField.DISK_DRIVER_STATUS, getDiskStatusInfo());
        result.put(HardwareInfoField.RAM_STATUS, getRamStatusInfo());
        result.put(HardwareInfoField.NETWORK_ADAPTER_STATUS, getNetworkStatusInfo());
        result.put(CommonField.EVENT_TIME, DateUtil.getFullTime());

        return result;
    }

    public static JSONObject getCpuStatusInfo() {
        JSONObject result = new JSONObject();

        CentralProcessor processor = hardware.getProcessor();
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        Util.sleep(1000);
        long[] ticks = processor.getSystemCpuLoadTicks();
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long total = user + nice + cSys + idle + iowait + irq + softirq + steal;
        double usage = 1.0 - (idle * 1.0 / total);

        result.put(CommonField.USED, total - idle);
        result.put(CommonField.TOTAL, total);
        result.put(CommonField.USAGE, new DecimalFormat("#.##%").format(usage));
        if (usage * 100 > 80){
            result.put(CommonField.STATUS, 1);
        }else{
            result.put(CommonField.STATUS, 0);
        }

        return result;
    }

    public static JSONObject getRamStatusInfo() {
        JSONObject result = new JSONObject();

        GlobalMemory globalMemory = hardware.getMemory();
        long idle = globalMemory.getAvailable();
        long total = globalMemory.getTotal();
        double usage = 1.0 - (idle * 1.0 / total);
//        String usage = new DecimalFormat("#.##%").format(1.0 - (idle * 1.0 / total));

        result.put(CommonField.USED, FormatSizeUtil.format(total - idle));
        result.put(CommonField.TOTAL, FormatSizeUtil.format(total));
        result.put(CommonField.USAGE, new DecimalFormat("#.##%").format(usage));
        if (usage * 100 > 80){
            result.put(CommonField.STATUS, 1);
        }else{
            result.put(CommonField.STATUS, 0);
        }

        return result;
    }

    public static List<JSONObject> getDiskStatusInfo() {
        List<JSONObject> result = new ArrayList<>();

        FileSystem fileSystem = operatingSystem.getFileSystem();
        List<OSFileStore> fsArray = fileSystem.getFileStores();
        for (OSFileStore fs : fsArray) {
            JSONObject item = new JSONObject();
            long idle = fs.getUsableSpace();
            long total = fs.getTotalSpace();
            String usage = new DecimalFormat("#.##%").format(1.0 - (idle * 1.0 / total));

//            if (total == 0L) continue;
            item.put(DiskDriverInfoField.DISK_NAME, fs.getName());
            item.put(CommonField.TYPE,fs.getType());
            item.put(CommonField.USED, FormatSizeUtil.format(total - idle));
            item.put(CommonField.TOTAL, FormatSizeUtil.format(total));
            item.put(CommonField.USAGE, usage);

            result.add(item);



        }
        return result;
    }

    public static JSONObject getNetworkStatusInfo() {

        HardwareAbstractionLayer hardware = new SystemInfo().getHardware();
        List<NetworkIF> adapterList = hardware.getNetworkIFs();

        Long firstReceive = 0L;
        Long firstSend = 0L;
        for (NetworkIF adapter : adapterList) {
            firstSend = firstSend + adapter.getBytesSent();
            firstReceive = firstReceive + adapter.getBytesRecv();
        }

        Long second = 1L;
        try{
            Thread.sleep(1000 * second);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        hardware = new SystemInfo().getHardware();
        adapterList = hardware.getNetworkIFs();

        Long secondReceive = 0L;
        Long secondSend = 0L;
        for (NetworkIF adapter : adapterList) {
            secondSend = secondSend + adapter.getBytesSent();
            secondReceive = secondReceive + adapter.getBytesRecv();
        }

        Long sendUsage = secondSend - firstSend;
        Long receiveUsage = secondReceive - firstReceive;

        JSONObject result = new JSONObject();
        result.put("send_usage", FormatSizeUtil.format(sendUsage) + "/s");
        result.put("receive_usage", FormatSizeUtil.format(receiveUsage) + "/s");

        long mb = 1048576L;
        if (sendUsage > 25 * mb){
            result.put("send_usage_status", 1);
        }else{
            result.put("send_usage_status", 0);
        }

        if (receiveUsage > 50 * mb){
            result.put("receive_usage_status", 1);
        }else{
            result.put("receive_usage_status", 0);
        }

        return result;
    }

}
